<?php
// +----------------------------------------------------------------------
// | ThinkCMF [ WE CAN DO IT MORE SIMPLE ]
// +----------------------------------------------------------------------
// | Copyright (c) 2013-2019 http://www.thinkcmf.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: 达达 <ccbox_net@163.com>
// +----------------------------------------------------------------------
namespace app\goods\lib\service;

use think\Model;
use think\view\driver\Think;

abstract class BaseService
{
    /**
     * 设置当前模型
     * @return string
     */
    abstract protected function setModel(): string;

    /**
     * 获取模型
     * @return Model
     */
    protected function getModel()
    {
        return app()->make($this->setModel());
    }

    /**
     * 查询条件过滤处理 : 过滤数据表中不存在的where条件字段
     * @param      $filter
     * @return array
     * @throws \think\db\exception\DbException
     */
    public function handleFilter(array $filter)
    {
        $fields = $this->getModel()->getTableFields();
        foreach ($filter as $key => $item) {
            if (is_array($item)) {
                if (!in_array($item[0], $fields))
                    unset($filter[$key]);
            } else {
                // if (!in_array($key, $fields))
                unset($filter[$key]);
            }
        }
        return $filter;
    }

    /**
     * 查询字段过滤处理 : 过滤数据表中不存在的字段
     * @param array|string $field
     * @return array
     * @throws \think\db\exception\DbException
     */
    public function handleField($field)
    {
        $fields = $this->getModel()->getTableFields();
        foreach ($field as $key => $item) {
            if (!in_array($item, $fields)) {
                unset($field[$key]);
            }
        }
        if (!count($field))
            $field = ['*'];
        return $field;
    }

    /**
     * 查询字段过滤处理 : 处理排序字段
     * @param array|string $sort
     * @return array
     * @throws \think\db\exception\DbException
     */
    public function handleSortField($sort)
    {
        // param $sort = 
        //          ['id'=>'asc'] 
        //          ['id']
        //          ['id' => '']
        //          'id asc' 'id,asc'
        // return $sort = [
        //          'id' => 'desc',
        //          'list_order' => 'asc'
        // ];

        if (is_string($sort)) {
            $sort = str_ireplace(' ', ',', $sort);
            $sort = str_ireplace('，', ',', $sort);
            $sort = str_ireplace('|', ',', $sort);
            $sortArray = explode(',', $sort);
            $sortType = isset($sortArray[1]) ? $sortArray[1] : 'desc';
            $sortType = $sortType == 'desc' ? 'desc' : 'asc';
            $sort = [$sortArray[0] => $sortType];
        }

        $fields = $this->getModel()->getTableFields();

        foreach ($sort as $key => $item) {
            if (!in_array($key, $fields)) {
                unset($sort[$key]);
            } else {
                $sort[$key] = $item == 'desc' ? 'desc' : 'asc';
            }
        }
        return $sort;
    }

    public function getQuery(array $filter, array $field = ['*'], array $sort = [], array $with = [])
    {
        $filter = $this->handleFilter($filter);
        $field = $this->handleField($field);

        return $this->getModel()
            ->where($filter)
            ->when(
                count($with),
                function ($query) use ($with) {
                    $query->with($with);
                }
            )
            ->field($field);
    }

    // public function setQueryFilter($filter){}

    /**
     * 条件获取列表-无分页
     * @param array $filter
     * @param array|string $field
     * @param array $sort
     * @param array|string $with
     * 
     * @return \think\Collection|array|static[]
     * 
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getListAll(array $filter, array $field = ['*'], array $sort = ['id' => 'desc'], array $with = [])
    {
        $sort = $this->handleSortField($sort);
        return $this
            ->getQuery($filter, $field, $with)
            ->order($sort)
            ->select();
    }

    /**
     * 条件获取分页列表
     * @param array $filter
     * @param array|string $field
     * @param array|string $sort
     * @param int $limit
     * @param array|string $with
     * 
     * @return \think\Paginator
     * 
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getListPage(array $filter, array $field = ['*'], array $sort = ['id' => 'desc'], int $limit = 0, array $with = [])
    {
        $limit = $limit ? $limit : (isset($filter['limit']) ? $filter['limit'] : 0);
        $sort = $this->handleSortField($sort);
        return $this
            ->getQuery($filter, $field, $with)
            ->order($sort)
            ->paginate($limit);
    }

    /**
     * 设置字段-状态
     * @param int|array $ids
     * @param string $status
     * @param string $statusField
     * @param string $timeField
     * @return
     */
    public function setStatus($ids, string $status, string $statusField = '', string $timeField = '')
    {
        $ids = is_int($ids) ? [$ids] : $ids;
        $update = [];
        if (!empty($statusField)) {
            $update[$statusField] = $status;
        }
        if (!empty($timeField)) {
            $update[$timeField] = time();
        }
        if(empty($update)){
            return false;
        }
        return $this->getModel()->where('id', 'in', $ids)->update($update);
    }

    /**
     * 根据id获取模型数据
     * @param int $id
     * @return bool
     */
    public function read(int $id)
    {
        return $this->getModel()->find($id);
    }

    /**
     * 保存模型数据
     * @param array $data
     * @param int $id
     * @return bool
     */
    public function save(array $data,int $id=0)
    {
        $model = $this->getModel();
        if($id>0){
            $row = $model->find($id);
            if(!empty($row)){
                return $row->save($data);
            }
        }
        return $model->save($data);
    }

}